package com.foodorder.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.foodorder.entity.Review;
import com.foodorder.exception.BusinessException;
import com.foodorder.model.PageResult;
import com.foodorder.model.request.ReviewAddRequest;
import com.foodorder.model.request.ReviewQueryRequest;
import com.foodorder.repository.ReviewRepository;
import com.foodorder.service.ReviewService;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.criteria.Predicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 评价服务实现类
 */
@Service
public class ReviewServiceImpl implements ReviewService {

    @Autowired
    private ReviewRepository reviewRepository;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    @Transactional
    public Review addReview(ReviewAddRequest request) {
        // 验证评分范围
        if (request.getRating() < 1 || request.getRating() > 5) {
            throw new BusinessException("评分必须在1-5之间");
        }

        Review review = new Review();
        review.setOrderId(request.getOrderId());
        review.setUserId(request.getUserId());
        review.setProductId(request.getProductId());
        review.setStoreId(request.getStoreId());
        review.setRating(request.getRating());
        review.setContent(request.getContent());
        review.setAnonymous(request.getAnonymous());
        review.setType(request.getType());
        review.setDisplay(true);
        review.setLikes(0);

        // 处理图片
        if (request.getImages() != null && !request.getImages().isEmpty()) {
            try {
                review.setImages(objectMapper.writeValueAsString(request.getImages()));
            } catch (JsonProcessingException e) {
                throw new BusinessException("图片处理失败");
            }
        }

        // 处理标签
        if (request.getTags() != null && !request.getTags().isEmpty()) {
            try {
                review.setTags(objectMapper.writeValueAsString(request.getTags()));
            } catch (JsonProcessingException e) {
                throw new BusinessException("标签处理失败");
            }
        }

        return reviewRepository.save(review);
    }

    @Override
    public Review getReviewById(Long id) {
        return reviewRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("评价不存在"));
    }

    @Override
    public PageResult<Review> getReviews(ReviewQueryRequest request) {
        // 构建查询条件
        Specification<Review> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 根据用户ID查询
            if (request.getUserId() != null) {
                predicates.add(cb.equal(root.get("userId"), request.getUserId()));
            }

            // 根据商品ID查询
            if (request.getProductId() != null) {
                predicates.add(cb.equal(root.get("productId"), request.getProductId()));
            }

            // 根据商店ID查询
            if (request.getStoreId() != null) {
                predicates.add(cb.equal(root.get("storeId"), request.getStoreId()));
            }

            // 根据订单ID查询
            if (request.getOrderId() != null) {
                predicates.add(cb.equal(root.get("orderId"), request.getOrderId()));
            }

            // 根据评价类型查询
            if (request.getType() != null) {
                predicates.add(cb.equal(root.get("type"), request.getType()));
            }

            // 评分范围查询
            if (request.getMinRating() != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("rating"), request.getMinRating()));
            }
            if (request.getMaxRating() != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("rating"), request.getMaxRating()));
            }

            // 只看有图评价
            if (request.getHasImage() != null && request.getHasImage()) {
                predicates.add(cb.isNotNull(root.get("images")));
                predicates.add(cb.notEqual(root.get("images"), ""));
                predicates.add(cb.notEqual(root.get("images"), "[]"));
            }

            // 根据标签查询
            if (StringUtils.hasText(request.getTag())) {
                predicates.add(cb.like(root.get("tags"), "%" + request.getTag() + "%"));
            }

            // 只显示显示状态的评价
            predicates.add(cb.equal(root.get("display"), true));

            return cb.and(predicates.toArray(new Predicate[0]));
        };

        // 构建排序
        Sort sort = "ASC".equalsIgnoreCase(request.getSortDirection()) ?
                Sort.by(request.getSortField()).ascending() :
                Sort.by(request.getSortField()).descending();

        // 创建分页请求
        PageRequest pageRequest = PageRequest.of(request.getPage(), request.getSize(), sort);

        // 查询数据
        Page<Review> page = reviewRepository.findAll(spec, pageRequest);

        // 转换为自定义分页结果
        return PageResult.of(
                page.getContent(),
                request.getPage(),
                request.getSize(),
                page.getTotalElements()
        );
    }

    @Override
    @Transactional
    public Review replyReview(Long id, String reply) {
        Review review = getReviewById(id);
        review.setReply(reply);
        review.setReplyTime(LocalDateTime.now());
        return reviewRepository.save(review);
    }

    @Override
    @Transactional
    public Review likeReview(Long id) {
        Review review = getReviewById(id);
        review.setLikes(review.getLikes() + 1);
        return reviewRepository.save(review);
    }

    @Override
    public Map<String, Object> getProductReviewStatistics(Long productId) {
        Map<String, Object> result = new HashMap<>();

        // 总评价数
        long totalCount = reviewRepository.countByProductIdAndDisplay(productId, true);
        result.put("totalCount", totalCount);

        if (totalCount > 0) {
            // 平均评分
            Double avgRating = reviewRepository.findAverageRatingByProductId(productId);
            result.put("avgRating", avgRating);

            // 好评率 (4-5星)
            long goodCount = reviewRepository.countByProductIdAndRatingGreaterThanEqualAndDisplay(productId, 4, true);
            result.put("goodRate", totalCount > 0 ? (double) goodCount / totalCount : 0);

            // 中评率 (3星)
            long normalCount = reviewRepository.countByProductIdAndRatingAndDisplay(productId, 3, true);
            result.put("normalRate", totalCount > 0 ? (double) normalCount / totalCount : 0);

            // 差评率 (1-2星)
            long badCount = reviewRepository.countByProductIdAndRatingLessThanEqualAndDisplay(productId, 2, true);
            result.put("badRate", totalCount > 0 ? (double) badCount / totalCount : 0);

            // 有图评价数
            long hasImageCount = reviewRepository.countByProductIdAndImagesNotNullAndImagesNotAndDisplay(
                    productId, "", true);
            result.put("hasImageCount", hasImageCount);
        } else {
            result.put("avgRating", 0.0);
            result.put("goodRate", 0.0);
            result.put("normalRate", 0.0);
            result.put("badRate", 0.0);
            result.put("hasImageCount", 0);
        }

        return result;
    }

    @Override
    public Map<String, Object> getStoreReviewStatistics(Long storeId) {
        Map<String, Object> result = new HashMap<>();

        // 总评价数
        long totalCount = reviewRepository.countByStoreIdAndDisplay(storeId, true);
        result.put("totalCount", totalCount);

        if (totalCount > 0) {
            // 平均评分
            Double avgRating = reviewRepository.findAverageRatingByStoreId(storeId);
            result.put("avgRating", avgRating);

            // 好评率 (4-5星)
            long goodCount = reviewRepository.countByStoreIdAndRatingGreaterThanEqualAndDisplay(storeId, 4, true);
            result.put("goodRate", totalCount > 0 ? (double) goodCount / totalCount : 0);

            // 中评率 (3星)
            long normalCount = reviewRepository.countByStoreIdAndRatingAndDisplay(storeId, 3, true);
            result.put("normalRate", totalCount > 0 ? (double) normalCount / totalCount : 0);

            // 差评率 (1-2星)
            long badCount = reviewRepository.countByStoreIdAndRatingLessThanEqualAndDisplay(storeId, 2, true);
            result.put("badRate", totalCount > 0 ? (double) badCount / totalCount : 0);

            // 最近30天评价数
            LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);
            long recentCount = reviewRepository.countByStoreIdAndCreatedAtAfterAndDisplay(
                    storeId, thirtyDaysAgo, true);
            result.put("recentCount", recentCount);
        } else {
            result.put("avgRating", 0.0);
            result.put("goodRate", 0.0);
            result.put("normalRate", 0.0);
            result.put("badRate", 0.0);
            result.put("recentCount", 0);
        }

        return result;
    }
} 